/*************************************************************************
	> File Name: main.cpp
	> Author:Meng Chen
	> Mail: meng_chen@bupt.edu.cn
	> Created Time: 2021 - 07 - 05 
 ************************************************************************/


#include <iostream>
#include <stdio.h>
#include <cstring>
#include <stdlib.h>
#include "absyn.h"
#include "symboltable.h"
#include "codegen.h"
#include "colorconsole.h"
#include "getopt.h"
using namespace std;
extern int yyparse(void);
extern FILE* yyin;

int NEED_PRINT_AST = 0;
int GET_OPTION_O = 0;

TreeNode savedTree;
vector<string> errMsg;

std::string OUTPUT_FILE = "output.asm";

const std::string PROJECT_NAME = 

"__________ _____    _________________    _____    _________   _____   \n"
"\\______  \\/  _  \\  /   _____/\\_____  \\  /  _  \\  /   _____/  /     \\  \n"
"|     ___/  /_\\  \\ \\_____  \\  /  ____/ /  /_\\  \\ \\_____  \\  /  \\ /  \\ \n"
"|    |  /    |    \\/        \\/       \\/    |    \\/        \\/    Y    \\ \n"
"|____|  \\____|__  /_______  /\\_______ \\____|__  /_______  /\\____|__  / \n"
                 "\t\t\\/        \\/         \\/       \\/        \\/         \\/ \n";


const std::string PROJECT_VERSION = "v0.1 by Group 4\n 2021 spring semester <<Compile principle Course designation>>\n"
                                    "in major of Data Science and Big data technology - group 4.\n";



Color::Modifier red(Color::FG_RED);
Color::Modifier def(Color::FG_DEFAULT);

bool has_suffix(const string &str, const string &suffix) {
  return str.size() >= suffix.size() &&
         str.compare(str.size() - suffix.size(), suffix.size(), suffix) == 0;
}

static void show_usage(char *argv[]) {
  cerr << "Usage: " << argv[0] << "\t<your-file>.pas [-h] [-o] [<file>] [-v] [-d]" << endl;
  cerr << "        -h                     Display help information." << endl;
  cerr << "        -o <file>              Place the output into <file>."
       << endl;
  cerr << "        -v                     Display compiler version information."
       << endl;
  cerr << "        -d                     Print  AST structure and info."
       << endl;
}

void parsing_parameters(int argc, char *argv[]) {
    int opt = 0;
    if (argc < 2 || argc == 2 || !has_suffix(string(argv[1]), ".pas")) {
        show_usage(argv);
        exit(0);
    }
    const char *optstring = "ho:vd";
    optind++;
    while ((opt = getopt(argc, argv, optstring)) != -1) {
        switch (opt) {
        case 'v':
            std::cout << PROJECT_NAME << " version: " << PROJECT_VERSION << endl;
            break;
        case 'o':
            OUTPUT_FILE = std::string(optarg);
            GET_OPTION_O = 1;
            break;
        case 'd':
            NEED_PRINT_AST = 1;
            break;
        case 'h':
        default:
            show_usage(argv);
            exit(0);
        }
    }
}

int main(int argc, char **argv)
{
    parsing_parameters(argc, argv);    
    if(GET_OPTION_O != 1) {
        return 0;
    }
    char* input = argv[1];
    std::string output = OUTPUT_FILE;
    FILE *fp = fopen(input, "r");
    if(fp == NULL)
    {
        cout<<"can not open file "<<input<<endl;
        exit(1);
    }
    yyin = fp;
    cout<<"Pascal2asm begin to work"<<endl;
    yyparse();
    fclose(fp);
    cout<<"AST generated"<<endl;
	if(errMsg.size()==0)
	{
        if(NEED_PRINT_AST == 1) {
            cout<<"****************---A---S---T---****************"<<endl;
            savedTree->printTree(savedTree,0);
            cout<<"****************---A---S---T---****************"<<endl;
        } else {
            cout<<"****************if need debug info, add option [-d]****************"<<endl;
        }
		CodeGenerator *instance = CodeGenerator::getinstance();
		CodeGenerator::init(instance);
		instance->generate(savedTree,output);
        
        cout<<"generate code done. Please check your assigned output file <" << output << ">" <<endl;
	}
	else
		for(int i = 0; i < errMsg.size(); i++)
            cout<<red<<"Error: "<<def<<errMsg.at(i)<<endl;
    return 0;
}
